<?php declare(strict_types=1);

/**
 * @author      guosir
 * @copyright   2023-2025 owner
 **/

namespace Srv\Apps\Apis\Order\Ctl;

use Srv\Apps\Apis\Common\DefCtl\DefChannelCtl;
use Srv\Apps\Apis\Common\DefCtl\DefUserRegTypeCtl;
use Srv\Apps\Apis\Common\IdxCtl\IdxIp;
use Srv\Apps\Apis\Skit\Ctl\SkitInfoCtl;
use Srv\Apps\Apis\User\Ctl\UserCtl;
use Srv\Apps\Proto\DTO\Order\PayOrderListDTO;
use Srv\Apps\Proto\Enum\Common\DeviceTypeEnum;
use Srv\Apps\Proto\Enum\GoodsCategoryEnum;
use Srv\Apps\Proto\Enum\PayResultEnum;
use Srv\Apps\Proto\Enum\PayTypeEnum;
use Srv\Apps\Proto\VO\DbJson\PayOrderDataBatchUnlockVO;
use Srv\Apps\Proto\VO\DbJson\PayOrderDataLotteryVO;
use Srv\Apps\Proto\VO\DbJson\PayOrderDataRechargeVO;
use Srv\Apps\Proto\VO\DbJson\PayOrderDataVipVO;
use Srv\Apps\Proto\VO\Order\PayOrderListVO;
use Srv\Apps\Proto\VO\Order\PayOrderVO;
use Srv\Apps\Proto\VO\Order\PayThreeOrderDataVO;
use Srv\Apps\Proto\VO\User\UserInfoBasicVO;
use Srv\Libs\Common\CommArray;
use Srv\Libs\Common\CommJson;
use Srv\Libs\Common\CommTime;
use Srv\Libs\Frame\ControllerAbstract;
use Srv\Libs\Frame\Page;
use Srv\Libs\Storage\DataMysql;
use Srv\Libs\Tools\IpAddr;

final class OrderCtl extends ControllerAbstract
{
    private ?DataMysql $DbAuto              = null;     // DB-Write

    /**
     * @return static
     * tag
     */
    final public static function tag():self
    {
        $thisObject                         = self::tagGet();
        if($thisObject instanceof self){
            $thisObject->DbAuto             = self::getDbAuto();
        }
        return $thisObject;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayOrderSrcByCode
     */
    public function getPayOrderSrcByCode(string $orderCode):array
    {
        if(strlen($orderCode) < 6) return [];
        $sql        = 'SELECT porr_id, porr_code, user_id, dup_id, pgsp_id, porr_key, porr_src, porr_category, porr_value, dcht_id, porr_ip, porr_device_type, porr_data, porr_amount, porr_back_time, porr_back_ip, porr_result, porr_pay_type, porr_create_time, porr_update_time FROM '.$this->DbAuto->getTableNameAll('pay_order_record').' WHERE porr_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\' AND porr_delete=0';
        return $this->DbAuto->getDataOne($sql);
    }

    /**
     * @param Page $Page
     * @param array $whereData
     * @return PayOrderListVO
     * getPayOrderList
     */
    public function getPayOrderList(Page $Page, array $whereData):?PayOrderListVO
    {
        $limitString        = $Page->getLimitString();
        $whereString        = ' WHERE porr_delete=0 ';
        $whereUserString    = ' WHERE user_delete=0 ';
        $userSearch         = false;
        // 检索条件
        if(count($whereData) > 0)foreach ($whereData as $key => $val){
            switch ($key){
                case PayOrderListDTO::_porrId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_id='. intval($val);
                    break;
                case PayOrderListDTO::_userId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='. intval($val);
                    break;
                case PayOrderListDTO::_pgspId:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'pgsp_id='. intval($val);
                    break;
                case PayOrderListDTO::_code:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_code LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case PayOrderListDTO::_key:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_key LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    break;
                case PayOrderListDTO::_category:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_category='.intval($val);
                    break;
                case PayOrderListDTO::_deviceType:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_device_type='.intval($val);
                    break;
                case PayOrderListDTO::_result:
                    $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_result='.intval($val);
                    break;
                case PayOrderListDTO::_payType:
                    $payType        = intval($val);
                    if($payType === PayTypeEnum::PAY_TYPE_STRIPE_PAYPAL){   // PayPal + Stripe
                        $payTypeList    = [PayTypeEnum::PAY_TYPE_PAYPAL, PayTypeEnum::PAY_TYPE_STRIPE];
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_pay_type IN('.implode(',', $payTypeList).')';
                    }else{
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'porr_pay_type='.$payType;
                    }
                    break;
                case PayOrderListDTO::_idNum:
                    if(strlen($val) > 10 && is_numeric($val)){
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id='.intval($val);
                    }else{
                        $tempSql        = 'SELECT user_id FROM '.$this->DbAuto->getTableNameAll('user_info').' WHERE usi_idnum LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\' AND usi_delete=0';
                        $whereString    .= (strlen($whereString)>0?' AND ':'').'user_id IN('.$tempSql.')';
                    }
                    break;
                case PayOrderListDTO::_mobile:
                    $durtId             = DefUserRegTypeCtl::tag()->getIdByKey(DefUserRegTypeCtl::KEY_REG_MOBILE);
                    $tempSql            = 'SELECT DISTINCT user_id FROM '.$this->DbAuto->getTableNameAll('user_bind_record').' WHERE usbr_delete=0 AND usbr_enable=1 AND durt_id='.$durtId.' AND usbr_openid LIKE \'%'.$this->DbAuto->getRealEscapeString($val).'%\'';
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'user_id IN('. $tempSql .')';
                    break;
                case PayOrderListDTO::_createTimeMin:
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'porr_create_time>='. intval($val);
                    break;
                case PayOrderListDTO::_createTimeMax:
                    $whereString        .= (strlen($whereString)>0?' AND ':'').'porr_create_time<='. intval($val);
                    break;
                case PayOrderListDTO::_channelMatch:
                    $userSearch             = true;
                    if($val === '1'){
                        $whereUserString    .= (strlen($whereUserString)>0?' AND ':'').'LENGTH(user_chnl_match)>0';
                    }else{
                        $whereUserString    .= (strlen($whereUserString)>0?' AND ':'').'user_chnl_match LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    }
                    break;
                case PayOrderListDTO::_pixelIdMatch:
                    $userSearch             = true;
                    if($val === '1'){
                        $whereUserString    .= (strlen($whereUserString)>0?' AND ':'').'LENGTH(user_pixel_id_match)>0';
                    }else{
                        $whereUserString    .= (strlen($whereUserString)>0?' AND ':'').'user_pixel_id_match LIKE \''.$this->DbAuto->getRealEscapeString($val).'%\'';
                    }
                    break;
                case PayOrderListDTO::_linkIdList:
                    $putIdList          = [];
                    $wappIdList         = [];
                    foreach ($val as $item){
                        if(!is_string($item)) continue;
                        $linkIdArr      = explode('_', $item);
                        $type           = intval($linkIdArr[0]??0);
                        $linkId         = intval($linkIdArr[1]??0);
                        if($type === 1){
                            if($linkId > 0) $putIdList[]    = $linkId;
                        }else if($type === 2){
                            if($linkId > 0) $wappIdList[]   = $linkId;
                        }
                    }
                    if(count($putIdList) > 0 && count($wappIdList) > 0){
                        $userSearch         = true;
                        $whereUserString    .= (strlen($whereUserString) > 0?' AND ':'').'(ptlr_id_match IN ('.implode(',', $putIdList).') OR walr_id_match IN ('.implode(',', $wappIdList).'))';
                    }else if(count($putIdList) > 0){
                        $userSearch         = true;
                        $whereUserString    .= (strlen($whereUserString) > 0?' AND ':'').'ptlr_id_match IN ('.implode(',', $putIdList).')';
                    }else if(count($wappIdList) > 0){
                        $userSearch         = true;
                        $whereUserString    .= (strlen($whereUserString) > 0?' AND ':'').'walr_id_match IN ('.implode(',', $wappIdList).')';
                    }
                    break;
                case PayOrderListDTO::_firstStatus:
                    $firstVal               = intval($val);
                    if($firstVal === 1){
                        // 用户首充订单, 首充成功第一单以及之前的未成功的订单
                        $whereString        .= (strlen($whereString) > 0?' AND ':'').'porr_id IN (SELECT porr_id FROM '.$this->DbAuto->getTableNameAll('pay_order_record').' AS order_record LEFT JOIN (SELECT user_id, MIN(porr_create_time) AS pay_min_time FROM '.$this->DbAuto->getTableNameAll('pay_order_record').' WHERE porr_result=1 AND porr_delete=0 GROUP BY user_id) AS order_user ON order_record.user_id=order_user.user_id AND order_record.porr_create_time<=order_user.pay_min_time WHERE order_user.user_id>0)';
                    }else if($firstVal === 2){
                        // 用户首充成功订单
                        $whereString        .= (strlen($whereString) > 0?' AND ':'').'porr_id IN (SELECT MIN(porr_id) AS porr_id_min FROM '.$this->DbAuto->getTableNameAll('pay_order_record').' WHERE porr_delete=0 AND porr_result=1 GROUP BY user_id )';
                    }
                    break;
            }
        }
        if($userSearch){
            $tempSql            = 'SELECT user_id FROM '.$this->DbAuto->getTableNameAll('user').$whereUserString;
            $whereString        .= (strlen($whereString)>0?' AND ':'').'user_id IN('. $tempSql .')';
        }
        $isFail                 = false;
        $sql                    = 'SELECT SQL_CALC_FOUND_ROWS porr_id, porr_code, user_id, dup_id, pgsp_id, porr_key, porr_src, porr_category, porr_value, dcht_id, porr_ip, porr_device_type, porr_data, porr_amount, porr_back_time, porr_back_ip, porr_result, porr_pay_type, porr_create_time, porr_update_time FROM '.$this->DbAuto->getTableNameAll('pay_order_record').$whereString.' ORDER BY porr_id DESC '.$limitString;
        $list                   = $this->DbAuto->getData($sql, $isFail);
        $totalNum               = $this->DbAuto->getDataInt('SELECT FOUND_ROWS() as num', 'num');
        if($isFail) return null;
        $PayOrderVOList         = [];
        $userIdList             = array_map('intval', array_column($list, 'user_id'));
        $UserInfoBasicVOList    = UserCtl::tag()->getUserInfoBasicBatch($userIdList);
        foreach($list as $item){
            $porrIdItem         = intval($item['porr_id']);
            if($porrIdItem < 1) continue;
            $PayOrderVO         = $this->getPayOrderVO($item);
            $userIdItem         = intval($item['user_id']);
            $UserInfoBasicVO    = $UserInfoBasicVOList[$userIdItem]??null;
            if($UserInfoBasicVO instanceof UserInfoBasicVO) $PayOrderVO->setUserInfoBasic($UserInfoBasicVO);
            if(!($PayOrderVO instanceof PayOrderVO)) continue;
            $PayOrderVOList[]   = $PayOrderVO;
        }
        $PayOrderListVO         = new PayOrderListVO();
        $PayOrderListVO->setList($PayOrderVOList);
        $PayOrderListVO->setPage($Page->getPageVO($totalNum));
        return $PayOrderListVO;
    }

    /**
     * @param array $order
     * @return PayOrderVO|null
     * getPayTplVO
     */
    public function getPayOrderVO(array $order): ?PayOrderVO
    {
        $porrId         = intval($order['porr_id']??0);
        if($porrId < 1) return null;
        $PayOrderVO     = new PayOrderVO();
        $PayOrderVO->setPorrId($porrId);
        $PayOrderVO->setCode($order['porr_code']);
        $PayOrderVO->setKey(trim($order['porr_key']));
        $PayOrderVO->setCategory(GoodsCategoryEnum::parseValue($order['porr_category']));
        $PayOrderVO->setValue(intval($order['porr_value']));
        $dchtId         = intval($order['dcht_id']);
        if($dchtId > 0){
            $channel    = DefChannelCtl::tag()->getExtStrById($dchtId, DefChannelCtl::EXT_NAME);
            $PayOrderVO->setChannel($channel);
        }
        $IpString       = IdxIp::tag()->getIpStrByIntStr($order['porr_ip']);
        $ipArea         = IpAddr::getLocationInfo($IpString);
        $PayOrderVO->setIpStr($IpString.'('.($ipArea['country']??'').')');
        $PayOrderVO->setDeviceType(DeviceTypeEnum::parseValue($order['porr_device_type']));
        $PayOrderVO->setPgspId(intval($order['pgsp_id']));
        if($PayOrderVO->getCategory() === GoodsCategoryEnum::GOODS_CATEGORY_VIP){
            $PayOrderDataVipVO      = new PayOrderDataVipVO();
            $PayOrderDataVipVO->mergeFromJsonStrTry($order['porr_data'], true);
            $PayOrderVO->setPayBuyVip($PayOrderDataVipVO);
        }
        if($PayOrderVO->getCategory() === GoodsCategoryEnum::GOODS_CATEGORY_RECHARGE){
            $PayOrderDataRechargeVO = new PayOrderDataRechargeVO();
            $PayOrderDataRechargeVO->mergeFromJsonStrTry($order['porr_data'], true);
            $PayOrderVO->setPayBuyRecharge($PayOrderDataRechargeVO);
        }
        if($PayOrderVO->getCategory() === GoodsCategoryEnum::GOODS_CATEGORY_BATCH_UNLOCK){
            $PayOrderDataBatchUnlockVO  = new PayOrderDataBatchUnlockVO();
            $PayOrderDataBatchUnlockVO->mergeFromJsonStrTry($order['porr_data'], true);
            $skitInfoSrc                = SkitInfoCtl::tag()->getSkitInfoSrc(intval($PayOrderDataBatchUnlockVO->getSkioId()));
            $seriesNum                  = count($PayOrderDataBatchUnlockVO->getSkssIdList());
            $name                       = '解锁'.$seriesNum.'集 - '.($skitInfoSrc['skio_id']??0).' - '.($skitInfoSrc['skio_name']??'');
            $PayOrderDataBatchUnlockVO->setName($name);
            $PayOrderVO->setPayBuyBatchUnlock($PayOrderDataBatchUnlockVO);
        }
        if($PayOrderVO->getCategory() === GoodsCategoryEnum::GOODS_CATEGORY_LOTTERY){
            $PayOrderDataLotteryVO  = new PayOrderDataLotteryVO();
            $PayOrderDataLotteryVO->mergeFromJsonStrTry($order['porr_data'], true);
            $PayOrderVO->setPayBuyLottery($PayOrderDataLotteryVO);
        }
        $PayOrderVO->setData($order['porr_data']);
        $PayOrderVO->setAmount(intval($order['porr_amount']));
        $PayOrderVO->setBackTime(intval($order['porr_back_time']));
        $backIpString   = IdxIp::tag()->getIpStrByIntStr($order['porr_back_ip']);
        $PayOrderVO->setBackIpStr($backIpString);
        $PayOrderVO->setResult(PayResultEnum::parseValue($order['porr_result']));
        $PayOrderVO->setPayType(PayTypeEnum::parseValue($order['porr_pay_type']));
        $PayOrderVO->setCreateTime(intval($order['porr_create_time']));
        $PayOrderVO->setUpdateTime(intval($order['porr_update_time']));
        $PayOrderVO->setPorrSrc(trim($order['porr_src']));
        $PayOrderVO->setThreeOrderCode($this->getPayThreeOrderCode($PayOrderVO->getCode(), $PayOrderVO->getPayType()));
        return $PayOrderVO;
    }

    /**
     * @param string $orderCode
     * @param int $type
     * @return string
     * 获取第三方订单号
     */
    public function getPayThreeOrderCode(string $orderCode, int $type):string
    {
        $threeOrderCode     = '';
        if(strlen($orderCode) < 6) return $threeOrderCode;
        switch ($type){
            case PayTypeEnum::PAY_TYPE_APPLE:
                $sql                = 'SELECT JSON_UNQUOTE(ptap_verify_data->\'$._payLoadDst.originalTransactionId\') AS three_order_code FROM '.$this->DbAuto->getTableNameAll('pay_record_apple_trans').' WHERE ptap_code= \''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
                $threeOrderCode     = $this->DbAuto->getDataString($sql, 'three_order_code');
                if(strlen($threeOrderCode) < 1){
                    $sql            = 'SELECT JSON_UNQUOTE(prap_verify_data->\'$.receipt.in_app[0].original_transaction_id\') AS three_order_code FROM '.$this->DbAuto->getTableNameAll('pay_record_apple').' WHERE prap_code= \''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
                    $threeOrderCode = $this->DbAuto->getDataString($sql, 'three_order_code');
                }
                break;
            case PayTypeEnum::PAY_TYPE_ALIPAY:
                $sql                = 'SELECT pral_out_trade_no FROM '.$this->DbAuto->getTableNameAll('pay_record_alipay').' WHERE pral_code= \''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
                $threeOrderCode     = $this->DbAuto->getDataString($sql, 'pral_out_trade_no');
                break;
            case PayTypeEnum::PAY_TYPE_WECHAT:
                $sql                = 'SELECT prwx_out_trade_no FROM '.$this->DbAuto->getTableNameAll('pay_record_weixin').' WHERE prwx_code= \''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
                $threeOrderCode     = $this->DbAuto->getDataString($sql, 'prwx_out_trade_no');
                break;
            case PayTypeEnum::PAY_TYPE_PAYPAL:
                $sql                = 'SELECT JSON_UNQUOTE(prpp_data->\'$.purchase_units[0].payments.captures[0].id\') AS three_order_code FROM '.$this->DbAuto->getTableNameAll('pay_record_paypal').' WHERE prpp_code= \''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
                $threeOrderCode     = $this->DbAuto->getDataString($sql, 'three_order_code');
                break;
            case PayTypeEnum::PAY_TYPE_GOOGLE:
                $sql                = 'SELECT prgg_order_id FROM '.$this->DbAuto->getTableNameAll('pay_record_google').' WHERE prgg_code= \''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
                $threeOrderCode     = $this->DbAuto->getDataString($sql, 'prgg_order_id');
                break;
            case PayTypeEnum::PAY_TYPE_STRIPE:
                $sql                = 'SELECT JSON_UNQUOTE(prst_data->\'$.payment_intent\') AS three_order_code FROM '.$this->DbAuto->getTableNameAll('pay_record_stripe').' WHERE prst_code= \''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
                $threeOrderCode     = $this->DbAuto->getDataString($sql, 'three_order_code');
                break;
        }
        if($threeOrderCode === 'null')  $threeOrderCode = '';
        return $threeOrderCode;
    }

    /**
     * @param string $orderCode
     * @param int $type
     * @return PayThreeOrderDataVO|null
     * getPayThreeOrderDataByCode
     */
    public function getPayThreeOrderDataByCode(string $orderCode, int $type):?PayThreeOrderDataVO
    {
        if(strlen($orderCode) < 6) return null;
        switch ($type){
            case PayTypeEnum::PAY_TYPE_APPLE:
                $listData       = $this->getPayRecordAppleTransDataByCode($orderCode);
                if(count($listData) < 1) $listData = $this->getPayRecordAppleDataByCode($orderCode);
                break;
            case PayTypeEnum::PAY_TYPE_ALIPAY:
                $listData       = $this->getPayRecordAlipayDataByCode($orderCode);
                break;
            case PayTypeEnum::PAY_TYPE_WECHAT:
                $listData       = $this->getPayRecordWeiXinDataByCode($orderCode);
                break;
            case PayTypeEnum::PAY_TYPE_PAYPAL:
                $listData       = $this->getPayRecordPaypalDataByCode($orderCode);
                break;
            case PayTypeEnum::PAY_TYPE_GOOGLE:
                $listData       = $this->getPayRecordGoogleDataByCode($orderCode);
                break;
            case PayTypeEnum::PAY_TYPE_STRIPE:
                $listData       = $this->getPayRecordStripeDataByCode($orderCode);
                break;
            default:
                return null;
        }
        $jsonData               = CommJson::encodeArray($listData);
        $PayThreeOrderDataVO    = new PayThreeOrderDataVO();
        $PayThreeOrderDataVO->setCode($orderCode);
        $PayThreeOrderDataVO->setJsonData($jsonData);
        return $PayThreeOrderDataVO;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayRecordAppleTransDataByCode
     */
    public function getPayRecordAppleTransDataByCode(string $orderCode):array
    {
        $listData   = [];
        if(strlen($orderCode) < 6) return $listData;
        $sql        = 'SELECT ptap_id, dup_id, user_id, ptap_ip, ptap_from_bundle_id, ptap_code, ptap_transaction_id, ptap_result, ptap_verify_data, ptap_original_transaction_id, ptap_bundle_id, ptap_product_id, ptap_purchase_date, ptap_original_purchase_date, ptap_quantity, ptap_in_app_ownership_type, ptap_signed_date_ms, ptap_type, ptap_app_account_token, ptap_environment, ptap_transaction_reason, ptap_storefront, ptap_storefront_id, ptap_currency, ptap_price, porr_id, ptap_retry_num, ptap_retry_time, ptap_create_time, ptap_update_time FROM '.$this->DbAuto->getTableNameAll('pay_record_apple_trans').' WHERE ptap_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
        $list       = $this->DbAuto->getData($sql);
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $ptapId                     = intval($item['ptap_id']??0);
                if($ptapId < 1) continue;
                $dupId                      = intval($item['dup_id']);
                $userId                     = intval($item['user_id']);
                $ipStr                      = strval($item['ptap_ip']);
                $fromBundleId               = trim($item['ptap_from_bundle_id']);
                $code                       = trim($item['ptap_code']);
                $transactionId              = trim($item['ptap_transaction_id']);
                $result                     = intval($item['ptap_result']);
                $verifyData                 = CommJson::decodeArray(trim($item['ptap_verify_data']??'[]'));
                $originalTransactionId      = trim($item['ptap_original_transaction_id']);
                $bundleId                   = trim($item['ptap_bundle_id']);
                $productId                  = trim($item['ptap_product_id']);
                $purchaseDate               = intval($item['ptap_purchase_date']);
                $originalPurchaseDate       = intval($item['ptap_original_purchase_date']);;
                $quantity                   = intval($item['ptap_quantity']);
                $inAppOwnershipType         = trim($item['ptap_in_app_ownership_type']);
                $signedDateMs               = intval($item['ptap_signed_date_ms']);
                $type                       = trim($item['ptap_type']);
                $appAccountToken            = trim($item['ptap_app_account_token']);
                $environment                = trim($item['ptap_environment']);
                $transactionReason          = trim($item['ptap_transaction_reason']);
                $storefront                 = trim($item['ptap_storefront']);
                $storefrontId               = trim($item['ptap_storefront_id']);
                $currency                   = trim($item['ptap_currency']);
                $price                      = intval($item['ptap_price']);
                $porrId                     = intval($item['porr_id']);
                $retryNum                   = intval($item['ptap_retry_num']);
                $retryTime                  = intval($item['ptap_retry_time']);
                $createTime                 = intval($item['ptap_create_time']);
                $updateTime                 = intval($item['ptap_update_time']);
                $listData[]                 = [
                    'ptapId'                    => $ptapId,
                    'dupId'                     => $dupId,
                    'userId'                    => $userId,
                    'ip'                        => IdxIp::tag()->getIpStrByIntStr($ipStr),
                    'fromBundleId'              => $fromBundleId,
                    'code'                      => $code,
                    'transactionId'             => $transactionId,
                    'result'                    => $result,
                    'verifyData'                => $verifyData,
                    'originalTransactionId'     => $originalTransactionId,
                    'bundleId'                  => $bundleId,
                    'productId'                 => $productId,
                    'purchaseDate'              => $purchaseDate,
                    'originalPurchaseDate'      => $originalPurchaseDate,
                    'quantity'                  => $quantity,
                    'inAppOwnershipType'        => $inAppOwnershipType,
                    'signedDateMs'              => $signedDateMs,
                    'type'                      => $type,
                    'appAccountToken'           => $appAccountToken,
                    'environment'               => $environment,
                    'transactionReason'         => $transactionReason,
                    'storefront'                => $storefront,
                    'storefrontId'              => $storefrontId,
                    'currency'                  => $currency,
                    'price'                     => $price,
                    'porrId'                    => $porrId,
                    'retryNum'                  => $retryNum,
                    'retryTime'                 => $retryTime,
                    'createTime'                => CommTime::getDateTime($createTime),
                    'updateTime'                => CommTime::getDateTime($updateTime)
                ];
            }
        }
        return $listData;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayRecordAppleDataByCode
     */
    public function getPayRecordAppleDataByCode(string $orderCode):array
    {
        $listData   = [];
        if(strlen($orderCode) < 6) return $listData;
        $sql        = 'SELECT prap_id, dup_id, user_id, prap_ip, prap_from_bundle_id, prap_code, prap_receipt_data_sha1, prap_receipt_data, prap_result, prap_verify_data, prap_in_app_num, prap_status, prap_receipt_type, prap_adam_id, prap_app_item_id, prap_bundle_id, prap_application_version, prap_download_id, prap_version_external_identifier, prap_receipt_creation_date_ms, prap_request_date_ms, prap_original_purchase_date_ms, prap_original_application_version, prap_retry_num, prap_retry_time, prap_create_time, prap_update_time FROM '.$this->DbAuto->getTableNameAll('pay_record_apple').' WHERE prap_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
        $list       = $this->DbAuto->getData($sql);
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $prapId                     = intval($item['prap_id']??0);
                if($prapId < 1) continue;
                $dupId                      = intval($item['dup_id']);
                $userId                     = intval($item['user_id']);
                $ipStr                      = strval($item['prap_ip']);
                $fromBundleId               = strval($item['prap_from_bundle_id']);
                $code                       = trim($item['prap_code']);
                $result                     = intval($item['prap_result']);
                $verifyData                 = CommJson::decodeArray(trim($item['prap_verify_data']??'[]'));
                $inAppNum                   = intval($item['prap_in_app_num']);
                $status                     = intval($item['prap_status']);
                $receiptType                = trim($item['prap_receipt_type']);
                $adamId                     = intval($item['prap_adam_id']);
                $appItemId                  = intval($item['prap_app_item_id']);;
                $bundleId                   = trim($item['prap_bundle_id']);
                $applicationVersion         = trim($item['prap_application_version']);
                $downloadId                 = intval($item['prap_download_id']);
                $versionExternalIdentifier  = intval($item['prap_version_external_identifier']);
                $receiptCreationDateMs      = intval($item['prap_receipt_creation_date_ms']);
                $requestDateMs              = intval($item['prap_request_date_ms']);
                $originalPurchaseDateMs     = intval($item['prap_original_purchase_date_ms']);
                $originalApplicationVersion = trim($item['prap_original_application_version']);
                $retryNum                   = intval($item['prap_retry_num']);
                $retryTime                  = intval($item['prap_retry_time']);
                $createTime                 = intval($item['prap_create_time']);
                $updateTime                 = intval($item['prap_update_time']);
                $listData[]                 = [
                    'prapId'                    => $prapId,
                    'dupId'                     => $dupId,
                    'userId'                    => $userId,
                    'ip'                        => IdxIp::tag()->getIpStrByIntStr($ipStr),
                    'fromBundleId'              => $fromBundleId,
                    'code'                      => $code,
                    'result'                    => $result,
                    'verifyData'                => $verifyData,
                    'inAppNum'                  => $inAppNum,
                    'status'                    => $status,
                    'receiptType'               => $receiptType,
                    'adamId'                    => $adamId,
                    'appItemId'                 => $appItemId,
                    'bundleId'                  => $bundleId,
                    'applicationVersion'        => $applicationVersion,
                    'downloadId'                => $downloadId,
                    'versionExternalIdentifier' => $versionExternalIdentifier,
                    'receiptCreationDateMs'     => $receiptCreationDateMs,
                    'requestDateMs'             => $requestDateMs,
                    'originalPurchaseDateMs'    => $originalPurchaseDateMs,
                    'originalApplicationVersion'=> $originalApplicationVersion,
                    'retryNum'                  => $retryNum,
                    'retryTime'                 => $retryTime,
                    'createTime'                => CommTime::getDateTime($createTime),
                    'updateTime'                => CommTime::getDateTime($updateTime)
                ];
            }
        }
        return $listData;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayRecordAlipayDataByCode
     */
    public function getPayRecordAlipayDataByCode(string $orderCode):array
    {
        $listData   = [];
        if(strlen($orderCode) < 6) return $listData;
        $sql        = 'SELECT pral_id, user_id, pral_code, pral_app_id, pral_method, pral_format, pral_charset, pral_sign_type, pral_sign, pral_timestamp, pral_version, pral_notify_url, pral_biz_content, pral_body, pral_subject, pral_out_trade_no, pral_timeout_express, pral_total_amount, pral_seller_id, pral_product_code, pral_ip, pral_delete, pral_create_time, pral_update_time FROM '.$this->DbAuto->getTableNameAll('pay_record_alipay').' WHERE pral_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\' AND pral_delete=0';
        $list       = $this->DbAuto->getData($sql);
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $pralId         = intval($item['pral_id']??0);
                if($pralId < 1) continue;
                $userId         = intval($item['user_id']);
                $code           = trim($item['pral_code']);
                $appId          = trim($item['pral_app_id']);
                $method         = trim($item['pral_method']);
                $format         = trim($item['pral_format']);
                $charset        = trim($item['pral_charset']);
                $signType       = trim($item['pral_sign_type']);
                $sign           = trim($item['pral_sign']);
                $timestamp      = trim($item['pral_timestamp']);
                $version        = trim($item['pral_version']);
                $notifyUrl      = trim($item['pral_notify_url']);
                $bizContent     = trim($item['pral_biz_content']);
                $body           = trim($item['pral_body']);
                $subject        = trim($item['pral_subject']);
                $outTradeNo     = trim($item['pral_out_trade_no']);
                $timeoutExpress = trim($item['pral_timeout_express']);
                $totalAmount    = intval($item['pral_total_amount']);
                $sellerId       = trim($item['pral_seller_id']);
                $productCode    = trim($item['pral_product_code']);
                $ipStr          = trim($item['pral_ip']);
                $createTime     = intval($item['pral_create_time']);
                $updateTime     = intval($item['pral_update_time']);
                $listData[]     = [
                    'pralId'        => $pralId,
                    'userId'        => $userId,
                    'code'          => $code,
                    'appId'         => $appId,
                    'method'        => $method,
                    'format'        => $format,
                    'charset'       => $charset,
                    'signType'      => $signType,
                    'sign'          => $sign,
                    'timestamp'     => $timestamp,
                    'version'       => $version,
                    'notifyUrl'     => $notifyUrl,
                    'bizContent'    => $bizContent,
                    'body'          => $body,
                    'subject'       => $subject,
                    'outTradeNo'    => $outTradeNo,
                    'timeoutExpress'=> $timeoutExpress,
                    'totalAmount'   => $totalAmount,
                    'sellerId'      => $sellerId,
                    'productCode'   => $productCode,
                    'ip'            => IdxIp::tag()->getIpStrByIntStr($ipStr),
                    'createTime'    => CommTime::getDateTime($createTime),
                    'updateTime'    => CommTime::getDateTime($updateTime),
                ];
            }
        }
        return $listData;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayRecordWeiXinDataByCode
     */
    public function getPayRecordWeiXinDataByCode(string $orderCode):array
    {
        $listData   = [];
        if(strlen($orderCode) < 6) return $listData;
        $sql        = 'SELECT prwx_id, user_id, prwx_code, prwx_appid, prwx_mch_id, prwx_device_info, prwx_nonce_str, prwx_sign, prwx_body, prwx_detail, prwx_attach, prwx_out_trade_no, prwx_fee_type, prwx_total_fee, prwx_spbill_create_ip, prwx_time_start, prwx_time_expire, prwx_goods_tag, prwx_notify_url, prwx_trade_type, prwx_limit_pay, prwx_return_code, prwx_return_msg, prwx_result_code, prwx_err_code, prwx_err_code_des, prwx_prepay_id, prwx_result, prwx_create_time, prwx_update_time FROM '.$this->DbAuto->getTableNameAll('pay_record_weixin').' WHERE prwx_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\' AND prwx_delete=0';
        $list       = $this->DbAuto->getData($sql);
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $prwxId             = intval($item['prwx_id']??0);
                if($prwxId < 1) continue;
                $userId             = intval($item['user_id']);
                $code               = trim($item['pral_code']);
                $appId              = trim($item['prwx_appid']);
                $mchId              = trim($item['pral_mch_id']);
                $deviceInfo         = trim($item['prwx_device_info']);
                $nonceStr           = trim($item['prwx_nonce_str']);
                $sign               = trim($item['prwx_sign']);
                $body               = trim($item['prwx_body']);
                $detail             = trim($item['prwx_detail']);
                $attach             = trim($item['prwx_attach']);
                $outTradeNo         = trim($item['prwx_out_trade_no']);
                $feeType            = trim($item['prwx_fee_type']);
                $totalFee           = intval($item['prwx_total_fee']);
                $spBillCreateIpStr  = trim($item['prwx_spbill_create_ip']);
                $timeStart          = intval($item['prwx_time_start']);
                $timeExpire         = intval($item['prwx_time_expire']);
                $goodsTag           = trim($item['prwx_goods_tag']);
                $notifyUrl          = trim($item['prwx_notify_url']);
                $tradeType          = trim($item['prwx_trade_type']);
                $limitPay           = trim($item['prwx_limit_pay']);
                $returnCode         = trim($item['prwx_return_code']);
                $returnMsg          = trim($item['prwx_return_msg']);
                $resultCode         = trim($item['prwx_result_code']);
                $errCode            = trim($item['prwx_err_code']);
                $errCodeDes         = trim($item['prwx_err_code_des']);
                $prepayId           = trim($item['prwx_prepay_id']);
                $result             = intval($item['prwx_result']);
                $createTime         = intval($item['prwx_create_time']);
                $updateTime         = intval($item['prwx_update_time']);
                $listData[]         = [
                    'prwxId'            => $prwxId,
                    'userId'            => $userId,
                    'code'              => $code,
                    'appId'             => $appId,
                    'mchId'             => $mchId,
                    'deviceInfo'        => $deviceInfo,
                    'nonceStr'          => $nonceStr,
                    'sign'              => $sign,
                    'body'              => $body,
                    'detail'            => $detail,
                    'attach'            => $attach,
                    'outTradeNo'        => $outTradeNo,
                    'feeType'           => $feeType,
                    'totalFee'          => $totalFee,
                    'spBillCreateIp'    => IdxIp::tag()->getIpStrByIntStr($spBillCreateIpStr),
                    'timeStart'         => $timeStart,
                    'timeExpire'        => $timeExpire,
                    'goodsTag'          => $goodsTag,
                    'notifyUrl'         => $notifyUrl,
                    'tradeType'         => $tradeType,
                    'limitPay'          => $limitPay,
                    'returnCode'        => $returnCode,
                    'returnMsg'         => $returnMsg,
                    'resultCode'        => $resultCode,
                    'errCode'           => $errCode,
                    'errCodeDes'        => $errCodeDes,
                    'prepayId'          => $prepayId,
                    'result'            => $result,
                    'createTime'        => CommTime::getDateTime($createTime),
                    'updateTime'        => CommTime::getDateTime($updateTime),
                ];
            }
        }
        return $listData;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayRecordPaypalDataByCode
     */
    public function getPayRecordPaypalDataByCode(string $orderCode):array
    {
        $listData   = [];
        if(strlen($orderCode) < 6) return $listData;
        $sql        = 'SELECT prpp_id, user_id, prpp_code, prpp_app_id, prpp_order_id, prpp_total_amount, prpp_amount_unit, prpp_ip, prpp_status, prpp_data, prpp_merchant_id, prpp_merchant_email, prpp_payer_id, prpp_payer_email, prpp_create_time, prpp_update_time FROM '.$this->DbAuto->getTableNameAll('pay_record_paypal').' WHERE prpp_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\' AND prpp_delete=0';
        $list       = $this->DbAuto->getData($sql);
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $prppId             = intval($item['prpp_id']??0);
                if($prppId < 1) continue;
                $userId             = intval($item['user_id']);
                $code               = trim($item['prpp_code']);
                $appId              = trim($item['prpp_app_id']);
                $orderId            = trim($item['prpp_order_id']);
                $totalAmount        = intval($item['prpp_total_amount']);
                $amountUnit         = trim($item['prpp_amount_unit']);
                $ipStr              = trim($item['prpp_ip']);
                $status             = trim($item['prpp_status']);
                $data               = trim($item['prpp_data']);
                $merchantId         = trim($item['prpp_merchant_id']);
                $merchantEmail      = trim($item['prpp_merchant_email']);
                $payerId            = trim($item['prpp_payer_id']);
                $payerEmail         = trim($item['prpp_payer_email']);
                $createTime         = intval($item['prpp_create_time']);
                $updateTime         = intval($item['prpp_update_time']);
                $listData[]         = [
                    'prppId'            => $prppId,
                    'userId'            => $userId,
                    'code'              => $code,
                    'appId'             => $appId,
                    'orderId'           => $orderId,
                    'totalAmount'       => $totalAmount,
                    'amountUnit'        => $amountUnit,
                    'ip'                => IdxIp::tag()->getIpStrByIntStr($ipStr),
                    'status'            => $status,
                    'data'              => CommJson::decodeArray($data),
                    'merchantId'        => $merchantId,
                    'merchantEmail'     => $merchantEmail,
                    'payerId'           => $payerId,
                    'payerEmail'        => $payerEmail,
                    'createTime'        => CommTime::getDateTime($createTime),
                    'updateTime'        => CommTime::getDateTime($updateTime),
                ];
            }
        }
        return $listData;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayRecordGoogleDataByCode
     */
    public function getPayRecordGoogleDataByCode(string $orderCode):array
    {
        $listData   = [];
        if(strlen($orderCode) < 6) return $listData;
        $sql        = 'SELECT prgg_id, dup_id, user_id, prgg_ip, prgg_code, prgg_package_name, prgg_ptoken_data_sha1, prgg_ptoken_data, prgg_result, prgg_verify_data, prgg_kind, prgg_purchase_time_mill, prgg_purchase_state, prgg_consumption_state, prgg_developer_payload, prgg_order_id, prgg_purchase_type, prgg_acknowledgement_state, prgg_purchase_token, prgg_product_id, prgg_quantity, prgg_obfuscated_external_account_id, prgg_obfuscated_external_profile_id, prgg_region_code, prgg_retry_num, prgg_retry_time, prgg_create_time, prgg_update_time FROM '.$this->DbAuto->getTableNameAll('pay_record_google').' WHERE prgg_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\'';
        $list       = $this->DbAuto->getData($sql);
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $prggId                         = intval($item['prgg_id']??0);
                if($prggId < 1) continue;
                $dupId                          = intval($item['dup_id']);
                $userId                         = intval($item['user_id']);
                $ipStr                          = trim($item['prgg_ip']);
                $code                           = trim($item['prgg_code']);
                $packageName                    = trim($item['prgg_package_name']);
                $result                         = intval($item['prgg_result']);
                $verifyData                     = trim($item['prgg_verify_data']);
                $kind                           = trim($item['prgg_kind']);
                $purchaseTimeMill               = intval($item['prgg_purchase_time_mill']);
                $purchaseState                  = intval($item['prgg_purchase_state']);
                $consumptionState               = intval($item['prgg_consumption_state']);
                $developerPayload               = trim($item['prgg_developer_payload']);
                $orderId                        = trim($item['prgg_order_id']);
                $purchaseType                   = intval($item['prgg_purchase_type']);
                $acknowledgementState           = intval($item['prgg_acknowledgement_state']);
                $purchaseToken                  = trim($item['prgg_purchase_token']);
                $productId                      = trim($item['prgg_product_id']);
                $quantity                       = intval($item['prgg_quantity']);
                $obfuscatedExternalAccountId    = trim($item['prgg_obfuscated_external_account_id']);
                $obfuscatedExternalProfileId    = trim($item['prgg_obfuscated_external_profile_id']);
                $regionCode                     = trim($item['prgg_region_code']);
                $retryNum                       = intval($item['prgg_retry_num']);
                $retryTime                      = intval($item['prgg_retry_time']);
                $createTime                     = intval($item['prgg_create_time']);
                $updateTime                     = intval($item['prgg_update_time']);
                $listData[]                     = [
                    'prggId'                        => $prggId,
                    'dupId'                         => $dupId,
                    'userId'                        => $userId,
                    'ip'                            => IdxIp::tag()->getIpStrByIntStr($ipStr),
                    'code'                          => $code,
                    'packageName'                   => $packageName,
                    'result'                        => $result,
                    'verifyData'                    => CommJson::decodeArray($verifyData),
                    'kind'                          => $kind,
                    'purchaseTimeMill'              => $purchaseTimeMill,
                    'purchaseState'                 => $purchaseState,
                    'consumptionState'              => $consumptionState,
                    'developerPayload'              => $developerPayload,
                    'orderId'                       => $orderId,
                    'purchaseType'                  => $purchaseType,
                    'acknowledgementState'          => $acknowledgementState,
                    'purchaseToken'                 => $purchaseToken,
                    'productId'                     => $productId,
                    'quantity'                      => $quantity,
                    'obfuscatedExternalAccountId'   => $obfuscatedExternalAccountId,
                    'obfuscatedExternalProfileId'   => $obfuscatedExternalProfileId,
                    'regionCode'                    => $regionCode,
                    'retryNum'                      => $retryNum,
                    'retryTime'                     => $retryTime,
                    'createTime'                    => CommTime::getDateTime($createTime),
                    'updateTime'                    => CommTime::getDateTime($updateTime),
                ];
            }
        }
        return $listData;
    }

    /**
     * @param string $orderCode
     * @return array
     * getPayRecordStripeDataByCode
     */
    public function getPayRecordStripeDataByCode(string $orderCode):array
    {
        $listData   = [];
        if(strlen($orderCode) < 6) return $listData;
        $sql        = 'SELECT prst_id, user_id, prst_code, prst_order_id, prst_total_amount, prst_amount_unit, prst_ip, prst_status, prst_mode, prst_live_mode, prst_data, prst_create_time, prst_update_time FROM '.$this->DbAuto->getTableNameAll('pay_record_stripe').' WHERE prst_code=\''.$this->DbAuto->getRealEscapeString($orderCode).'\' AND prst_delete=0';
        $list       = $this->DbAuto->getData($sql);
        if(CommArray::isForeach($list)){
            foreach ($list as $item){
                $prstId                 = intval($item['prst_id']??0);
                if($prstId < 1) continue;
                $userId                 = intval($item['user_id']);
                $code                   = trim($item['prst_code']);
                $orderId                = trim($item['prst_order_id']);
                $totalAmount            = intval($item['prst_total_amount']);
                $amountUnit             = trim($item['prst_amount_unit']);
                $ipStr                  = trim($item['prst_ip']);
                $status                 = trim($item['prst_status']);
                $mode                   = trim($item['prst_mode']);
                $liveMode               = intval($item['prst_live_mode']);
                $data                   = trim($item['prst_data']);
                $createTime             = intval($item['prst_create_time']);
                $updateTime             = intval($item['prst_update_time']);
                $listData[]             = [
                    'prstId'            => $prstId,
                    'userId'            => $userId,
                    'code'              => $code,
                    'orderId'           => $orderId,
                    'totalAmount'       => $totalAmount,
                    'amountUnit'        => $amountUnit,
                    'ip'                => IdxIp::tag()->getIpStrByIntStr($ipStr),
                    'status'            => $status,
                    'mode'              => $mode,
                    'liveMode'          => $liveMode,
                    'data'              => CommJson::decodeArray($data),
                    'createTime'        => CommTime::getDateTime($createTime),
                    'updateTime'        => CommTime::getDateTime($updateTime),
                ];
            }
        }
        return $listData;
    }
}
